#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <assert.h>
#include <signal.h>
#include <time.h>
#include <sys/types.h>
#include <pthread.h>
#include <stdarg.h>
#include <sys/time.h>
#include <stdint.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "cJSON.h"
#include "utils_ptrlist.h"
#include "ts_mqtt.h"
#include "utils_common.h"
#include "core.h"
#include "app.h"
#include "protocol.h"
#include "tcpproxy.h"

#define SERVER_CONFIG_FILE "./serverCfg.json"
static const char *defaultConfig =
    "{\r\n"
    "    \"mqservice\": \"mqtt://172.16.13.155:1883\",\r\n"
    "    \"heartBeatEnable\": true,\r\n"
    "    \"heartbeat_interval\": 3000,\r\n"
    "    \"base_port\":2000,\r\n"
    "    \"server_ip\":\"192.168.1.123\",\r\n"
    "    \"service_id\": \"123123\"\r\n"
    "}";

static char service_id[64] = {0};
static char server_ip[64] = {0};
static int base_port = 2000;
static HANDLE gMQHandle = NULL;
extern void trace_log(const char *fmt, ...);
extern void lprintf(const char *fmt, ...);

#include "utils_net.h"

//
static int get_available_bridge_port(int *port_up, int *port_down, int *socket_up, int *socket_down)
{
    int i = 0;
    int _base_port = base_port;
    int fd_up, fd_down;
    int port = 0;
    int find = 0;
    for (i = 0; i < 100; i++)
    {
        port = _base_port + i * 2;
        fd_up = sock_listen(port, NULL, 5);
        if (fd_up <= 0)
            continue;
        fd_down = sock_listen(port + 1, NULL, 5);
        if (fd_down <= 0)
        {
            close(fd_up);
            continue;
        }
        *port_up = port;
        *port_down = port + 1;
        *socket_up = fd_up;
        *socket_down = fd_down;
        find = 1;
        break;
    }
    return find;
}

extern void DesctoryObject(const char *service_id);
extern void CreateForwardObject(CientInfo *info, const char *service_id, int port_up, int port_down, int fd_up, int fd_down);
extern int GetForwardServiceCount();

void OnClientConnceted(CientInfo *info)
{
    char topic[256] = {0};
    char buffer[256] = {0};
    sprintf(topic, "iot/%s/bridge", info->device_id);
    sprintf(buffer, "{\"client_id\":\"%s\",\"server_ip\":\"%s\",\"server_port\":%d,\"bridge_ip\":\"%s\",\"bridge_port\":%d}",
            info->client_id, info->server_ip, info->device_port, info->bridge_ip, info->bridge_port);
    MQClient_Publish(gMQHandle, 1, topic, buffer, strlen(buffer));
}

void OnDeviceConnceted(CientInfo *info, int code, const char *msg)
{
    char topic[256] = {0};
    char buffer[256] = {0};
    //
    sprintf(topic, "iot/%s/status", info->device_id);
    sprintf(buffer, "{\"code\":%d,\"msg\":\"%s\"}", code, msg);
    MQClient_Publish(gMQHandle, 1, topic, buffer, strlen(buffer));
}

static void ParseJsonData(HANDLE h, RecvMessageS *msg)
{
    cJSON *json = NULL;
    char buffer[1024] = {0};
    char topic[256] = {0};
    char text[256] = {0};
    char client_id[64] = {0};
    char value[256] = {0};
    char service_id_ex[24] = {0};
    CientInfo info = {0};
    char device_id[64] = {0};
    int code = 0;
    int port_up, port_down, fd_up, fd_down;
    if (msg->len > 0)
        strncpy(buffer, msg->text, msg->len);
    strcpy(value, msg->topic);
    json = cJSON_Parse(buffer);
    if (!json)
    {
        trace_log("Error parsing\r\n");
        return;
    }
    if (strcmp(value, "iot/bridge/start") == 0)
    {
        if (GetForwardServiceCount() > 20)
            DesctoryObject(GetForwardServiceId(0));
        strcpy(info.client_id, json_get_string_safe(json, "client_id", "123"));
        strcpy(info.device_id, json_get_string_safe(json, "device_id", "123"));
        strcpy(info.bridge_ip, json_get_string_safe(json, "bridge_ip", "127.0.0.1"));
        info.bridge_port = json_get_int_safe(json, "bridge_port", 23);
        strcpy(info.server_ip, server_ip);
        if (get_available_bridge_port(&port_up, &port_down, &fd_up, &fd_down))
        {
            info.server_port = port_up;
            info.device_port = port_down;
            sprintf(text, "{\"code\":0,\"server_ip\":\"%s\",\"server_port\":%d}", server_ip, port_up);
            sprintf(topic, "iot/%s/bridgeinfo", info.client_id);
            MQClient_Publish(h, 1, topic, text, strlen(text));
        }
        else
        {
            sprintf(text, "{\"code\":404,\",\"server_ip\":\"\",server_port\":0}");
            sprintf(topic, "iot/%s/bridgeinfo", info.client_id);
            MQClient_Publish(h, 1, topic, text, strlen(text));
        }
        CreateForwardObject(&info, info.client_id, port_up, port_down, fd_up, fd_down);
    }
    else if (strcmp(value, "iot/bridge/stop") == 0)
    {
        strcpy(client_id, json_get_string_safe(json, "client_id", "123"));
        sprintf(topic, "iot/%s/status", client_id);
        strcpy(buffer, "{\"code\":\"0\",\"msg\":\"拆线完成\"}");
        MQClient_Publish(h, 1, topic, buffer, strlen(buffer));
        DesctoryObject(client_id);
    }
    else if (strcmp(value, "iot/bridge/clear") == 0)
    {
        strcpy(client_id, json_get_string_safe(json, "client_id", "123"));
        sprintf(topic, "iot/%s/status", client_id);
        strcpy(buffer, "{\"code\":\"0\",\"msg\":\"拆除所有\"}");
        MQClient_Publish(h, 1, topic, buffer, strlen(buffer));
        ProxyDropAllClient();
        DesctoryAllObject();
    }
    // else if (strcmp(value, "iot/bridge/response") == 0)
    // {
    //     strcpy(device_id, json_get_string_safe(json, "device_id", "123"));
    //     code = json_get_int_safe(json, "code", "123");
    //     if (FindForwardClientId(device_id, client_id))
    //     {
    //         sprintf(topic, "iot/%s/status", client_id);
    //         sprintf(buffer, "{\"code\":%d,\"device_id\":\"%s\"}", code, device_id);
    //         MQClient_Publish(h, 1, topic, buffer, strlen(buffer));
    //     }
    //     else
    //     {
    //         sprintf(topic, "iot/%s/error", client_id);
    //         sprintf(buffer, "{\"code\":404\"msg\":\"not find client_id\"}");
    //         MQClient_Publish(h, 1, topic, buffer, strlen(buffer));
    //     }
    // }
    cJSON_Delete(json);
}

static void onMqttEvent(HANDLE h, int code, RecvMessageS *msg)
{
    switch (code)
    {
    case MQ_EVT_ONLINE:
        break;
    case MQ_EVT_OFFLINE:
        break;
    case MQ_EVT_HEARTBEAT:
        break;
    case MQ_EVT_DATAREADY:
        ParseJsonData(h, msg);
        break;
    default:
        break;
    }
}

static void loadSysConfig()
{
    const char *buffer = NULL;
    char topic[256] = {0};
    char strip_buffer[1024] = {0};
    int size;
    MQTTClientConfig cfg = {0};
    if (access(SERVER_CONFIG_FILE, F_OK) != 0)
        write_file_raw(SERVER_CONFIG_FILE, (char *)defaultConfig, strlen(defaultConfig));
    buffer = read_file_raw(SERVER_CONFIG_FILE, &size);
    string_remove_head_tail_space(buffer, strip_buffer);
    free(buffer);
    trace_log("load Dev config success.\r\n");
    printf("%s\r\n", strip_buffer);
    cJSON *root = cJSON_Parse(strip_buffer);
    if (!root)
    {
        trace_log("Error parsing\r\n");
        return;
    }
    strcpy(cfg.mqtt_username, json_get_string_safe(root, "mqtt_username", "transpeed"));
    strcpy(cfg.mqtt_password, json_get_string_safe(root, "mqtt_password", "transpeed"));
    strcpy(cfg.mqtt_url, json_get_string_safe(root, "mqservice", "mqtt://47.116.13.41:1883"));
    cfg.mqtt_heartBeatEnable = json_get_bool_safe(root, "mqtt_heartBeatEnable", FALSE);
    cfg.mqtt_heartBeatInterval = json_get_int_safe(root, "mqtt_heartBeatInterval", 30000);
    base_port = json_get_int_safe(root, "base_port", 2000);
    //

    strcpy(cfg.mqtt_url, MQTT_URL);
    strcpy(cfg.mqtt_username, MQTT_USER_NAME);
    strcpy(cfg.mqtt_password, MQTT_PASSWORD);

    cfg.will_retain = 1;
    strcpy(service_id, json_get_string_safe(root, "service_id", "123"));
    strcpy(server_ip, json_get_string_safe(root, "server_ip", "123"));
    sprintf(cfg.mqtt_client_id, "server_%s", service_id);
    strcpy(cfg.mqtt_will_topic, "iot/bridge/server/offline");
    sprintf(cfg.mqtt_willmsg, "{\"service_id\":\"%s\"}", service_id);
    trace_log("mqtt login user %s pwd:%s \r\n", cfg.mqtt_username, cfg.mqtt_password);
    trace_log("server_ip:%s,service_id:%s\r\n", server_ip, service_id);
    cJSON_Delete(root);
    MQService_Init();
    gMQHandle = MQClient_New(&cfg, onMqttEvent);
    if (!gMQHandle)
    {
        trace_log("MQClient_New error.\r\n");
        return;
    }
    //
    sprintf(topic, "iot/bridge/start");
    MQClient_SubPreDefined(gMQHandle, 1, topic);
    sprintf(topic, "iot/bridge/stop");
    MQClient_SubPreDefined(gMQHandle, 1, topic);
    sprintf(topic, "iot/bridge/clear");
    MQClient_SubPreDefined(gMQHandle, 1, topic);
    // sprintf(topic, "iot/bridge/response");
    // MQClient_SubPreDefined(gMQHandle, 1, topic);
    MQService_Enable(1);
}

void service_run()
{
    loadSysConfig();
    ProxyStart();
}

void service_stop()
{
}